package com.ifp.opengate.boot.filter;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import com.ifp.core.context.ClogicContext;
import com.ifp.core.flow.service.FlowService;
import com.ifp.core.log.LogHandle;
import com.ifp.core.log.Trace;
import com.ifp.core.util.SpringContextsUtil;
import com.ifp.opengate.boot.constants.Constants;
import com.ifp.opengate.boot.task.AccessCacheDataSyncTask;
import com.ifp.opengate.boot.task.ApiDeployTask;
import com.ifp.opengate.boot.utils.RequestUtil;
import com.ifp.opengate.boot.utils.SeqUtil;

import reactor.core.publisher.Mono;

/**
 * @Classname FlinkAnaslysisFliter
 * @Description TODO
 * @Date 2019/6/4 10:00
 * @Created by zzh
 *          <p>
 *          zhuzh@belink.com
 *          </p>
 * @Version 1.0
 */
@Component
public class StartFliter implements GlobalFilter, Ordered {

    private static final String UNKNOWN = "unknown";
    private static final String LOCALHOST = "127.0.0.1";
    private static final String SEPARATOR = ",";

    private static final String HEADER_X_FORWARDED_FOR = "x-forwarded-for";
    private static final String HEADER_PROXY_CLIENT_IP = "Proxy-Client-IP";
    private static final String HEADER_WL_PROXY_CLIENT_IP = "WL-Proxy-Client-IP";
    //
    // @Autowired
    // DataPublishService dataPublishService;

    @Autowired
    LogHandle logHandle;

    @Autowired
    SeqUtil seqUtil;

    @Value("${spring.application.name}")
    String appName = "default";

    /**
     * 输出结果渲染处理器
     */
    // @Autowired
    // private RenderHandle renderHandle;

    @Autowired
    private ApiDeployTask apiDeployTask;

    @Autowired
    private AccessCacheDataSyncTask accessCacheDataSyncHandler;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        long millis = System.currentTimeMillis();
        logHandle.init();
        exchange.getAttributes().put("requestTime", millis);
        exchange.getAttributes().put(Constants.GLOBALLOGID, logHandle.getFlumeLogReqId());
        exchange.getAttributes().put(Constants.APP_ID_NAME, RequestUtil.getActionId(exchange.getRequest()));
        InetSocketAddress remoteAddress = exchange.getRequest().getRemoteAddress();
        InetAddress address = remoteAddress.getAddress();
        Trace.logInfo(Trace.MODULE_ACTION, "start filter 请求的 ip {}", address.getHostAddress());
        return chain.filter(exchange).then(Mono.fromRunnable(() -> flinkAnalysis(exchange, millis)));
    }

    private void flinkAnalysis(ServerWebExchange exchange, long millis) {
        ClogicContext clogicContext = exchange.getAttribute("clContext");
        if (null != clogicContext) {
            logMockResult(exchange, clogicContext);
            Map<String, Object> tempMap = clogicContext.getTempMap();
            Map<String, Object> logMap = (Map<String, Object>)tempMap.get(Constants.LOG_MA_MAP);
            // sendDataToQueue(logMap, millis, exchange);
            Trace.log(Trace.MODULE_TRACE, Trace.LEVEL_INFO, "{} this request time is {}",
                exchange.getAttributes().get(Constants.GLOBALLOGID), System.currentTimeMillis() - millis);
        }
    }

    /**
     * 记录案例成功执行结果
     * 
     * @param exchange
     * @param clogicContext
     */
    private void logMockResult(ServerWebExchange exchange, ClogicContext clogicContext) {
        Object logId = exchange.getAttributes().get(Constants.GLOBALLOGID);
        try {
            Trace.logInfo(Trace.MODULE_COMMON, "{} 记录案例执行结果 start...", logId);
            if (!"5".equals(clogicContext.getTempMap().get("gwTmpKeySandBoxFlag"))) {
                Trace.logInfo(Trace.MODULE_COMMON, "{} 记录案例执行结果：非沙箱请求，无需记录", logId);
                return;
            }
            String caseId = (String)clogicContext.getTempMap().get("gwTmpKeySandBoxCaseId");
            if (org.apache.commons.lang3.StringUtils.isBlank(caseId) || "null".equals(caseId)) {
                Trace.logInfo(Trace.MODULE_COMMON, "{} 记录案例执行结果：没有caseId，执行案例失败，不记录", logId);
                return;
            }
            // 记录成功案例
            /*
             * AbstractRPCConnector connector = (AbstractRPCConnector)
             * SpringContextsUtil.getBean("RPCIFP2ServiceConnector"+random);
             * connector.setVersion((String)
             * clogicContext.getTempMap().get(Constants.SUBCRIBE_VERSION)); Object recObj =
             * connector.sendAndReceive(apiName, consumerId, dataMap);
             */
            FlowService flowService = (FlowService)SpringContextsUtil.getRemoteBean("GW660001" + Constants.SUBSCRIBER);
            Map<String, Object> sendContextMap = new HashMap<>(4);
            Map<String, Object> sendDataMap = new HashMap<>(4);
            sendDataMap.put("appId", clogicContext.getTempMap().get(Constants.APP_ID));
            sendDataMap.put("caseId", caseId);
            sendDataMap.put("bsnType", "1");// 成功
            sendContextMap.put("dataMap", sendDataMap);
            Map<String, Object> respMap = flowService.execute(sendContextMap);
            // Trace.logInfo(Trace.MODULE_COMMON, "记录案例执行结果 完成,执行结果：{}", JsonUtil.toJSON(respMap));
        } catch (Exception e) {
            Trace.logError(Trace.MODULE_COMMON, "{} 记录案例执行结果 异常 {}", logId, e);
        }
    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }

    /**
     * 获取真实客户端IP
     * 
     * @param serverHttpRequest
     * @return
     */
    public static String getRealIpAddress(ServerHttpRequest serverHttpRequest) {
        String ipAddress;
        try {
            // 1.根据常见的代理服务器转发的请求ip存放协议，从请求头获取原始请求ip。值类似于203.98.182.163, 203.98.182.163
            ipAddress = serverHttpRequest.getHeaders().getFirst(HEADER_X_FORWARDED_FOR);
            if (ipAddress == null || UNKNOWN.equalsIgnoreCase(ipAddress)) {
                ipAddress = serverHttpRequest.getHeaders().getFirst(HEADER_PROXY_CLIENT_IP);
            }
            if (ipAddress == null || UNKNOWN.equalsIgnoreCase(ipAddress)) {
                ipAddress = serverHttpRequest.getHeaders().getFirst(HEADER_WL_PROXY_CLIENT_IP);
            }
            // 2.如果没有转发的ip，则取当前通信的请求端的ip
            if (ipAddress == null || UNKNOWN.equalsIgnoreCase(ipAddress)) {
                InetSocketAddress inetSocketAddress = serverHttpRequest.getRemoteAddress();
                if (inetSocketAddress != null) {
                    ipAddress = inetSocketAddress.getAddress().getHostAddress();
                }
                // 如果是127.0.0.1，则取本地真实ip
                if (LOCALHOST.equals(ipAddress)) {
                    InetAddress localAddress = InetAddress.getLocalHost();
                    if (localAddress.getHostAddress() != null) {
                        ipAddress = localAddress.getHostAddress();
                    }
                }
            }
            if (ipAddress != null) {
                ipAddress = ipAddress.split(SEPARATOR)[0].trim();
            }
        } catch (Exception e) {
            ipAddress = "";
        }
        return ipAddress == null ? "" : ipAddress;
    }

    public static void main(String[] args) {
        String st =
            "{header={requestTime=20200715194013340,signData=,charset=UTF-8,requestId=30200715194013340298019,appId=33614738674815301826,version=1.0.0,chnlId=99,servcId=ebbc_pot_qry_0002,serviceCode=ebbc_pot_qry_0002,termnId=,userId=UR000005256001,userCertLevel=,reqTime=2020-06-23 16:33:23.995,bizTrackNo=OPEN2007091033120001,reqSeqNo=OPEN2007091033120001,pageSize=0,offset=0,hostIp=10.0.192.78,behavCode=TRAN_POTS_0004,bzTransId=20001100000120200619000000000062,transId=33600000120200619000000000000062,channelId=336,clientTyp=200011,chnlCd=0103,srvSysCd=053,reqIP=10.0.192.78,merchantNo=26016165957821475155,responseId=OPB01202007241101261002,consumerId=ebbc_pot_qry_0002,apiName=ebbc_pot_qry_0002},body={potType=0,spcCode=0,ecifCustNo=}";
        System.out.println(st.toString().replace(",", "&").replace("{", "").replace("}", ""));
    }
}
